﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Shine.Util.Regular;
using Shine.Util.IO;

namespace Shine.Util.Data
{
    /// <summary>
    /// 数据库连接配置信息
    /// </summary>
    [Serializable]
    public class DbConnectionInfo
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public DbConnectionInfo()
        {
            //DbType = "Oracle";
        }

        /// <summary>
        /// 获取或设置配置实例名称
        /// </summary>
        [XmlAttribute]
        public string Name { get; set; }

        /// <summary>
        /// 获取或设置服务器的IP地址或服务名，若有特殊的端口则在ip地址后加上端口，如126.33.9.157:1522
        /// Oracle：IP地址或实例名称；
        /// Sql：IP地址；
        /// Access：数据文件全路径
        /// </summary>
        [XmlAttribute]
        public string Server { get; set; }

        /// <summary>
        /// 获取或设置数据库用户名称
        /// </summary>
        [XmlAttribute]
        public string UserID { get; set; }

        /// <summary>
        /// 获取或设置数据库密码
        /// </summary>
        [XmlAttribute]
        public string Password { get; set; }

        /// <summary>
        /// 获取或设置数据库实例名称。
        /// Oracle：服务名称，可在【服务】中查看，默认为orcl；
        /// Sql：访问的数据库名称；
        /// Access：为空。
        /// </summary>
        [XmlAttribute]
        public string SID { get; set; }

        /// <summary>
        /// 数据库类型：Access、Oracle、Sql
        /// </summary>
        [XmlAttribute]
        public string DBType { get; set; }

        /// <summary>
        /// 获取服务器的实例名称，若Server为IP地址，则返回 IP/SID；否则返回Server
        /// </summary>
        public string IntanceName
        {
            get
            {
                if (string.IsNullOrWhiteSpace(Server)) return "";
                if (VerifyHelper.IsIP(Server)) return Server + "/" + SID;
                return Server;
            }
        }

        /// <summary>
        /// 获取数据库的连接字符串
        /// </summary>
        /// <returns></returns>
        public string GetConnectString()
        {
            if ("Access".Equals(DBType, StringComparison.CurrentCultureIgnoreCase))
            {
                string path = this.Server.Trim();
                if (path.StartsWith("\\"))
                {
                    path = PathHelper.GetAppPath() + path;
                }

                if (string.IsNullOrWhiteSpace(this.Password))
                    return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path;
                else
                    return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";User ID=admin;Password=;Jet OLEDB:Database Password=" + this.Password;
            }
            else if ("Sql".Equals(DBType, StringComparison.CurrentCultureIgnoreCase))
            {
                return "";
            }
            else if ("Oracle".Equals(DBType, StringComparison.CurrentCultureIgnoreCase))
            {
                return GetOracleString();
            }
            else
            {
                return Server;
            }
        }

        /// <summary>
        /// 获取Oracle直连字符串,直接使用IP进行连接
        /// </summary>
        /// <returns></returns>
        public string GetOracleString()
        {
            Valid();
            if ("localhost".Equals(Server, StringComparison.CurrentCultureIgnoreCase) || VerifyHelper.IsIP(Server))
            {
                if (string.IsNullOrEmpty(SID) || string.IsNullOrWhiteSpace(SID)) SID = "orcl";
                return string.Format("Data Source={0}/{1};User ID={2};Password={3}", Server, SID, UserID, Password);
            }
            else
                return string.Format("Data Source={0};User ID={1};Password={2}", Server, UserID, Password);
        }

        /// <summary>
        /// 获取Oracle直连字符串 ADDRESS_LIST
        /// </summary>
        /// <returns></returns>
        public string GetOracleString2()
        {
            Valid();
            string ip = Server;
            string port = "1521";
            if (Server.Contains(":"))
            {
                string[] tmps = Server.Split(':');
                ip = tmps[0];
                port = string.IsNullOrEmpty(tmps[1]) ? "1521" : tmps[1];
            }
            StringBuilder sb = new StringBuilder();
            sb.Append("Data Source=(DESCRIPTION=");
            sb.Append("(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={0})(PORT={1}))) ");
            sb.Append("(CONNECT_DATA=(SERVICE_NAME={2}))); User Id={3};Password={4};");
            return string.Format(sb.ToString(), ip, port.ToString(), SID, UserID, Password);
        }

        /// <summary>
        /// 获取sde直连字符串
        /// </summary>
        /// <returns></returns>
        public string GetSDEString()
        {
            Valid();
            if (string.IsNullOrEmpty(SID) || string.IsNullOrWhiteSpace(SID))
                SID = "orcl";
            if ("localhost".Equals(Server, StringComparison.CurrentCultureIgnoreCase) || VerifyHelper.IsIP(Server))
                return string.Format("Instance=sde:oracle${0}/{1};User={2};Password={3};DBCLIENT=oracle", Server, SID, UserID, Password);
            else
                return string.Format("Instance=sde:oracle11g:{0};User={1};Password={2}", Server, UserID, Password);
        }

        /// <summary>
        /// 获取EF的连接字符串
        /// </summary>
        /// <returns></returns>
        public string GetEFString()
        {
            Valid();
            if (string.IsNullOrEmpty(SID) || string.IsNullOrWhiteSpace(SID))
                SID = "orcl";
            if ("localhost".Equals(Server, StringComparison.CurrentCultureIgnoreCase) || VerifyHelper.IsIP(Server))
                return "metadata=res://*/EF.csdl|res://*/EF.ssdl|res://*/EF.msl;provider=Oracle.DataAccess.Client;provider connection string=\"DATA SOURCE=" + Server + "/" + SID + ";PASSWORD=" + Password + ";PERSIST SECURITY INFO=True;USER ID=" + UserID + "\"";
            else
                return "metadata=res://*/EF.csdl|res://*/EF.ssdl|res://*/EF.msl;provider=Oracle.DataAccess.Client;provider connection string=\"DATA SOURCE=" + Server + ";PASSWORD=" + Password + ";PERSIST SECURITY INFO=True;USER ID=" + UserID + "\"";
        }

        /// <summary>
        /// 验证参数是否正确
        /// </summary>
        /// <returns></returns>
        private void Valid()
        {
            if (string.IsNullOrEmpty(Server))
                throw new Exception("服务器不能为空，需要设置服务器的IP地址或服务名，若有特殊的端口则在ip地址后加上端口，如126.33.9.157:1522");
            if (string.IsNullOrEmpty(UserID))
                throw new Exception("用户名不能为空");
            if(string.IsNullOrEmpty(Password))
                throw new Exception("密码不能为空");
            //if ("localhost".Equals(Server, StringComparison.CurrentCultureIgnoreCase))
            //    Server = "127.0.0.1";
        }
                
        /// <summary>
        /// 根据连接字符串创建连接对象实例
        /// </summary>
        /// <param name="connectstring">连接字符串</param>
        /// <returns></returns>
        public static DbConnectionInfo CreateConnectString(string connectstring)
        {
            DbConnectionInfo entry=new DbConnectionInfo();
            string[] vs = connectstring.Split(';');
            foreach (string s in vs)
            {
                if (string.IsNullOrEmpty(s)) continue;
                string[] itm = s.Split('=');
                string key = itm[0].Trim();
                string sv = itm[1].Trim();
                if (key.Equals("Instance", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (sv.Contains("$"))
                    {  
                        string[] tmp = sv.Split('$')[1].Split('/');
                        entry.SID = string.IsNullOrEmpty(tmp[1]) ? "orcl" : tmp[1];
                        entry.Server = tmp[0];                        
                    }
                    else
                    {
                        entry.Server = sv.Split(':')[2];
                    }
                }
                else if (key.Equals("Data Source", StringComparison.CurrentCultureIgnoreCase))
                {
                    if (sv.Contains("/"))
                    {
                        string[] tmp = sv.Split('/');
                        entry.SID = string.IsNullOrEmpty(tmp[1]) ? "orcl" : tmp[1];
                        entry.Server = tmp[0];
                    }
                    else
                    {
                        entry.Server = sv;
                    }
                }
                else if (key.Equals("User", StringComparison.CurrentCultureIgnoreCase))
                    entry.UserID = sv;
                else if (key.Equals("Password", StringComparison.CurrentCultureIgnoreCase))
                    entry.Password = sv;
            }
            return entry;
        }
    }
}
